home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Presentations / Presentations ’90 / A⁄Rose Techniques / ClTool / Printer.c < prev   
Encoding:
C/C++ Source or Header  |  1988-11-07  |  14.1 KB  |  624 lines  |  [TEXT/MPS ]

  1. /*
  2.  *    Printer.c - Routines for printing.
  3.  *    Mark D. Rustad    86/06/06.
  4.  */
  5.  
  6. /*
  7.  *    Include files.
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <ctype.h>
  13. #include <Clister.h>
  14.  
  15. #include <Types.h>
  16. #include <CursorCtl.h>
  17. #include <Memory.h>
  18. #include <Errors.h>
  19. #include <Files.h>
  20. #include <Fonts.h>
  21. #include <PrintTraps.h>
  22. #include <Resources.h>
  23. #include <Windows.h>
  24.  
  25. _TITLE("Printer.c - Routines for printing.")
  26. _SPACE("4,10,definitions")
  27. /*
  28.  *    Include global definitions.
  29.  */
  30.  
  31. #include "glob.h"
  32.  
  33.  
  34. /*
  35.  *    Private definitions.
  36.  */
  37.  
  38. struct pinfo            /* Page information structure    */
  39. {
  40.     char    *titlp;        /* Pointer to title for page        */
  41.     char    *stitp;        /* Pointer to subtitle for page        */
  42.     char    *sstitp;    /* Pointer to subsubtitle for page    */
  43.     long    fpos;        /* File position for page            */
  44.     long    lineno;        /* Starting line number for page    */
  45. };
  46.  
  47.  
  48. /*
  49.  *    Private globals.
  50.  */
  51.  
  52. static THPrint    prRecHdl;            /* Handle to print record    */
  53. static TPPrPort    myPrPort;            /* Pointer to print port    */
  54. static Rect    border;                    /* Rectangle of page    */
  55. static Rect    TxtRect;                /* Rectangle for text    */
  56.  
  57. static long    Last_pos;                /* Last file position        */
  58. static struct pinfo    *Pinfp = 0L;    /* Pointer to Pinfo array    */
  59. static short    HdrLineHgt;            /* Header line height    */
  60. static short    HdrLineStart;        /* Header line starting point */
  61. static short    TxtLineHgt;            /* Text line height    */
  62. static short    TxtLineStart;        /* Text line starting point */
  63. static short    Lineno;                /* Number of lines on page    */
  64. static short    Pointctr;            /* Point counter            */
  65. static short    Pageno;                /* Page number                */
  66. static short    Pagesz;                /* No. of lines on a page    */
  67. static short    Flineno;            /* Line number in file        */
  68. static short    Blklns;                /* No. of blank lines skipped    */
  69. static char    *Dtime;                    /* Points to date/time string    */
  70.  
  71. _SPACE("4,10,print_job")
  72. /*
  73.  *    print_job - Print selected files.
  74.  *
  75.  *    Calls:    dofile, fclose, fopen, memset, NewHandle, PrClose, PrintDefault,
  76.  *        PrOpen, PrOpenDoc
  77.  */
  78.  
  79. void print_job()
  80. {
  81.     short    i;
  82.     TPrStatus    myStRec;
  83.     THPrint    ResHdl;
  84.     Rect    windowrect;
  85.     WindowRecord    wrec;
  86.     FMetricRec    firec;
  87.     short    MyRFNum, RFNum;
  88.     void    dofile();
  89.  
  90.     SetFractEnable(1);                    /* Enable fractional spacing    */
  91.     windowrect.top = windowrect.left = 1;
  92.     windowrect.bottom = windowrect.right = 2;
  93.     strcpy(Tmpstr, Finfo[0].fname);
  94.     if (Nfiles > 1)
  95.         strcat(Tmpstr, ", et. al.");
  96.     newwindow((Ptr)&wrec, &windowrect, Tmpstr, 1, plainDBox, (WindowPtr)-1, 0, 0);
  97.  
  98.     MyRFNum = CurResFile();
  99.     if ((prRecHdl = ResHdl = (THPrint)Get1Resource('PSup', 128)) == 0)
  100.         prRecHdl = (THPrint)NewHandle(sizeof(TPrint));
  101.     PrOpen();
  102.     if (ResHdl == 0)
  103.         PrintDefault(prRecHdl);
  104.     if (PSOpt)
  105.     {
  106.         if (PrStlDialog(prRecHdl))
  107.         {
  108.             RFNum = CurResFile();
  109.             if (ResHdl == 0)
  110.             {
  111.                 UseResFile(MyRFNum);
  112.                 AddResource((Handle)prRecHdl, 'PSup', 128, "\p");
  113.                 UseResFile(RFNum);
  114.             }
  115.             else
  116.             {
  117.                 ChangedResource((Handle)ResHdl);
  118.             }
  119.             UpdateResFile(MyRFNum);
  120.         }
  121.     }
  122.     else
  123.         PrValidate(prRecHdl);
  124.  
  125. //    if (PrJobDialog(prRecHdl))
  126.     {
  127.         Fixed    ftmp;
  128.  
  129.         myPrPort = PrOpenDoc(prRecHdl, 0, 0);
  130.         border = (**prRecHdl).prInfo.rPage;
  131.         TextFont(HFNum);
  132.         TextSize(HFSize);
  133.         FontMetrics(&firec);
  134.         ftmp = ((firec.ascent + firec.descent + firec.leading) * LSOpt) / 100;
  135.         HdrLineHgt = ((ftmp + 0x8000) >> 16) & 0xFFFF;
  136.         ftmp = firec.ascent + 0x8000;
  137.         HdrLineStart = border.top + ((ftmp >> 16) & 0xFFFF) + (2 + 2);
  138.         if (HOpt)
  139.             TxtLineStart = (3 * HdrLineHgt) + (2 + 2) + (2 + 2);
  140.         else
  141.             TxtLineStart = (2 + 2);
  142.  
  143.         TextFont(TFNum);
  144.         TextSize(TFSize);
  145.         FontMetrics(&firec);
  146.         ftmp = ((firec.ascent + firec.descent + firec.leading) * LSOpt) / 100;
  147.         TxtLineHgt = ((ftmp + 0x8000) >> 16) & 0xFFFF;
  148.         ftmp = firec.ascent + 0x8000;
  149.         TxtLineStart += border.top + ((ftmp >> 16) & 0xFFFF);
  150.         
  151.         Pagesz = (border.bottom - TxtLineStart - (2 + 2)) / TxtLineHgt;
  152.         if (ROpt)
  153.         {
  154.             for (i = Nfiles - 1; i >= 0; --i)    /* Print in reverse order    */
  155.             {
  156.                 if ((Fd = fopen(Finfo[i].fname, "r")) == NULL)
  157.                     continue;
  158.         
  159.                 dofile(Finfo + i);
  160.                 fclose(Fd);
  161.                 free(Finfo[i].fname);    /* Free space used by file name */
  162.                 Finfo[i].fname = 0;
  163.             }
  164.         }
  165.         else
  166.         {
  167.             for (i = 0; i < Nfiles; ++i)        /* Print in forward order    */
  168.             {
  169.                 if ((Fd = fopen(Finfo[i].fname, "r")) == NULL)
  170.                     continue;
  171.         
  172.                 dofile(Finfo + i);
  173.                 fclose(Fd);
  174.                 free(Finfo[i].fname);    /* Free space used by file name */
  175.                 Finfo[i].fname = 0;
  176.             }
  177.         }
  178.         PrCloseDoc(myPrPort);
  179.         if (PrError() == noErr && (*prRecHdl)->prJob.bJDocLoop == bSpoolLoop)
  180.             PrPicFile(prRecHdl, 0, 0, 0, &myStRec);
  181.     }
  182.  
  183.     PrClose();
  184.     CloseWindow((WindowPtr)&wrec);
  185. }
  186.  
  187. _SPACE("4,10,dofile")
  188. /*
  189.  *    dofile - Process one file.
  190.  *
  191.  *    Inputs:
  192.  *        fip        (param) - finfo pointer.
  193.  *        Fd        - File descriptor.
  194.  *        Pagesz    - No. of lines on page.
  195.  *
  196.  *    Calls:    countit, fgets, free, fseek, gettime, ppd, printit,
  197.  *        printline, sprintf, strncpy, tscan
  198.  */
  199.  
  200.  static void    dofile(fip)
  201.  struct finfo    *fip;
  202.  {
  203.     int        i, j;            /* Loop index    */
  204.     short    pix;            /* Pinfo index    */
  205.     char    *gettime();
  206.     void    countit(), tscan();
  207.     extern char    *calloc();
  208.  
  209.     Dtime = gettime();        /* Get edited ASCII time    */
  210.     Blklns = Pageno = 0;
  211.     Lineno = Pagesz;        /* Force eject on first printable line    */
  212.  
  213.     if (Init_title[0] == '\0')    /* If title not set by -t    */
  214.         strncpy(Init_title, fip->fname, TITLESIZE);    /* Use filename as title    */
  215.  
  216.     tscan();                /* Scan up to 100 lines for _TITLE    */
  217.     strncpy(Title, Init_title, TITLESIZE);
  218.  
  219.     Pinfp = (struct pinfo *)calloc(MAXPAGES + 1, sizeof(struct pinfo));
  220.     if (Pinfp == 0L)        /* If calloc fails, give up    */
  221.     {
  222.         Init_title[0] = Subtitle[0] = Subsubtitle[0] = '\0';    /* Clear Title    */
  223.         return;
  224.     }
  225.  
  226.     Last_pos = 0;
  227.     for (Flineno = 1; fgets(LineBuf, MAXLINE, Fd) != 0;
  228.         ++Flineno, Last_pos = ftell(Fd))
  229.     {
  230.         for (i = 0; isspace(LineBuf[i]); ++i)
  231.             if (LineBuf[i] == '\f')
  232.             {
  233.                 LineBuf[i] = ' ';
  234.                 Lineno = Pagesz;                    /* Force eject    */
  235.             }
  236.         if (LineBuf[i] == '\0')
  237.         {
  238.             ++Blklns;        /* Count blank line skipped    */
  239.             continue;        /* Skip blank line            */
  240.         }
  241.  
  242.         for (j = i; LineBuf[j]; ++j)    /* Check for form feed on line */
  243.             if (LineBuf[j] == '\f')
  244.             {
  245.                 LineBuf[j] = ' ';
  246.                 Lineno = Pagesz;                    /* Force eject    */
  247.             }
  248.  
  249.         if (LineBuf[i] == '_' && ppd(&LineBuf[i]))    /* If directive    */
  250.             Blklns = 0;        /* Ignore blank lines before directive    */
  251.         else
  252.             countit();        /* Print non-directive line    */
  253.     }
  254.  
  255.     if (Pageno != 0)        /* If anything to print */
  256.     {
  257.         if (ROpt)
  258.         {
  259.             for (pix = Pageno; pix > 0; --pix)
  260.                 dopage(pix, fip);
  261.         }
  262.         else
  263.         {
  264.             for (pix = 1; pix <= Pageno; ++pix)
  265.                 dopage(pix, fip);
  266.         }
  267.  
  268.         /*    Free any remaining title, subtitle or sub-subtitle strings.    */
  269.  
  270.         if (Pinfp[0].titlp != 0L)
  271.             free(Pinfp[0].titlp);
  272.         if (Pinfp[0].stitp != 0L)
  273.             free(Pinfp[0].stitp);
  274.         if (Pinfp[0].sstitp != 0L)
  275.             free(Pinfp[0].sstitp);
  276.     }
  277.  
  278.     free(Pinfp);
  279.     Init_title[0] = Subtitle[0] = Subsubtitle[0] = '\0';    /* Clear Title    */
  280. }
  281.  
  282. _SPACE("4,20,countit")
  283. /*
  284.  *    countit - Count line.
  285.  *
  286.  *    Counts printable lines during the first pass of laser printing and
  287.  *    sets up Pinfp entries for each page.
  288.  *
  289.  *    Inputs:
  290.  *        Flineno        - Current line number in file.
  291.  *        Last_pos    - File position for start of this line.
  292.  *        Subsubtitle    - Pointer to subsubtitle string.
  293.  *        Subtitle    - Pointer to subtitle string.
  294.  *        Title        - Pointer to title string.
  295.  *
  296.  *    Throughputs:
  297.  *        Blklns    - Cleared.
  298.  *        Lineno    - Incremented to indicate current line on page.
  299.  *        Pageno    - Incremented for each new page.
  300.  *        Pinfp    - Updated for each page.
  301.  *
  302.  *    Calls:    upd_str_ptr
  303.  */
  304.  
  305. static void countit()
  306. {
  307.     char    *upd_str_ptr();
  308.  
  309.     if (++Lineno + Blklns >= Pagesz)
  310.     {
  311.         Lineno = 1;
  312.         Blklns = 0;
  313.  
  314.         if (Pageno < MAXPAGES)    /* File will be truncated if > MAXPAGES    */
  315.         {
  316.             Pinfp[Pageno+1].titlp = upd_str_ptr(Pinfp[Pageno].titlp, Title);
  317.             Pinfp[Pageno+1].stitp = upd_str_ptr(Pinfp[Pageno].stitp, Subtitle);
  318.             Pinfp[Pageno+1].sstitp = upd_str_ptr(Pinfp[Pageno].sstitp, Subsubtitle);
  319.  
  320.             ++Pageno;
  321.             SpinCursor(-4);
  322.             Pinfp[Pageno].fpos = Last_pos;
  323.             Pinfp[Pageno].lineno = Flineno;
  324.         }
  325.         return;
  326.     }
  327.  
  328.     Lineno += Blklns;            /* Advance Lineno for skipped blank lines    */
  329.  
  330.     Blklns = 0;
  331. }
  332.  
  333. _SPACE("4,20,dopage")
  334. /*
  335.  *    dopage - Print one page.
  336.  */
  337.  
  338. static    dopage(pix, fip)
  339. int    pix;                    /* Page index */
  340. struct finfo    *fip;
  341. {
  342.     int        i, j;
  343.     void    printit(), printline();
  344.     extern long    fseek();
  345.  
  346.     SpinCursor(4);
  347.     PrOpenPage(myPrPort, 0);
  348.     if (BOpt)
  349.     {
  350.         PenSize(2, 2);
  351.         FrameRoundRect(&border, 16, 16);
  352.         if (HOpt)
  353.         {
  354.             MoveTo(border.left, TxtLineStart - 4);
  355.             LineTo(border.right, TxtLineStart - 4);
  356.         }
  357.     }
  358.  
  359.     PenSize(1, 1);
  360.     if (HOpt)
  361.     {
  362.         TextFont(HFNum);
  363.         TextSize(HFSize);
  364.     
  365.         if (Pinfp[pix].titlp)
  366.         {
  367.             MoveTo(border.left + 8, HdrLineStart);
  368.             drawstring(Pinfp[pix].titlp);
  369.         }
  370.         sprintf(Tmpstr, "%s   Page %d of %d", Dtime, pix, Pageno);
  371.         MoveTo(border.right - stringwidth(Tmpstr) - 8, HdrLineStart);
  372.         drawstring(Tmpstr);
  373.     
  374.         if (Pinfp[pix].stitp)
  375.         {
  376.             MoveTo(border.left + 8, HdrLineStart + HdrLineHgt);
  377.             drawstring(Pinfp[pix].stitp);
  378.         }
  379.         if (POpt)
  380.         {
  381.             MoveTo(border.right - StringWidth(*Prop_str) - 8, HdrLineStart + HdrLineHgt);
  382.             DrawString(*Prop_str);
  383.         }
  384.     
  385.         if (Pinfp[pix].sstitp)
  386.         {
  387.             MoveTo(border.left + 8, HdrLineStart + HdrLineHgt + HdrLineHgt);
  388.             drawstring(Pinfp[pix].sstitp);
  389.         }
  390.     }
  391.  
  392.     TextFont(TFNum);
  393.     TextSize(TFSize);
  394.     Lineno = Blklns = 0;
  395.     Pointctr = TxtLineStart;
  396.  
  397.     /* Position to start of page    */
  398.     fseek(Fd, Pinfp[pix].fpos, 0);
  399.  
  400.     /* Print page    */
  401.     for (Flineno = Pinfp[pix].lineno;
  402.         fgets(LineBuf, MAXLINE, Fd) != 0; ++Flineno)
  403.     {
  404.         for (i = 0; isspace(LineBuf[i]); ++i)
  405.             if (LineBuf[i] == '\f')
  406.             {
  407.                 LineBuf[i] = ' ';
  408.                 Lineno = Pagesz;                    /* Force eject    */
  409.             }
  410.         if (LineBuf[i] == '\0')
  411.         {
  412.             ++Blklns;        /* Count blank line skipped    */
  413.             continue;        /* Skip blank line            */
  414.         }
  415.  
  416.         for (j = i; LineBuf[j]; ++j)    /* Check for form feed on line */
  417.             if (LineBuf[j] == '\f')
  418.             {
  419.                 LineBuf[j] = ' ';
  420.                 Lineno = Pagesz;                    /* Force eject    */
  421.             }
  422.  
  423.         if (LineBuf[i] == '_' && ppd(&LineBuf[i]))    /* If directive    */
  424.             Blklns = 0;        /* Ignore blank lines before directive    */
  425.         else
  426.         {
  427.             if (++Lineno + Blklns >= Pagesz)
  428.             {
  429.                 int    offset;
  430.  
  431.                 offset = 1 - (ROpt * 2);
  432.                 if (Pinfp[pix+offset].titlp != Pinfp[pix].titlp
  433.                     && Pinfp[pix].titlp)
  434.                     free(Pinfp[pix].titlp);
  435.                 if (Pinfp[pix+offset].stitp != Pinfp[pix].stitp
  436.                     && Pinfp[pix].stitp)
  437.                     free(Pinfp[pix].stitp);
  438.                 if (Pinfp[pix+offset].sstitp != Pinfp[pix].sstitp
  439.                     && Pinfp[pix].sstitp)
  440.                     free(Pinfp[pix].sstitp);
  441.                 break;
  442.             }
  443.             printit(fip);        /* Print non-directive line    */
  444.         }
  445.     }
  446.  
  447.     PrClosePage(myPrPort);
  448. }
  449.  
  450. _SPACE("4,25,ppd")
  451. /*
  452.  *    ppd - Process possible directive.
  453.  *
  454.  *    Inputs:
  455.  *        buf        - (param) Address of possible directive.
  456.  *        Laser    - Flag indicating laser printing.
  457.  *        Pagesz    - Length of page, in lines.
  458.  *
  459.  *    Outputs:    Returns true if directive processed.
  460.  *
  461.  *    Throughputs:
  462.  *        Lineno    - Line number on current page may be incremented
  463.  *                to allow for whitespace output by this routine or may be
  464.  *                set to a large value to force a page eject later in
  465.  *                printit.
  466.  *        Title    - The current title will be changed in processing of
  467.  *                a _TITLE directive.
  468.  *        Subtitle    - The current subtitle will be changed in
  469.  *                processing of a _SUBTITLE directive.
  470.  *        Subsubtitle    - The current sub-subtitle will be changed in
  471.  *                processing of a _SPACE directive if the optional third
  472.  *                argument is present.
  473.  *
  474.  *    Calls:    collect, sscanf, strncmp.
  475.  */
  476.  
  477. static    ppd(buf)
  478. char    buf[];
  479. {
  480.     long    lcnt, scnt;
  481.     char    item[TITLESIZE+2];
  482.  
  483.     if (strncmp(buf, "_SPACE", 6) == 0)    /* If SPACE directive    */
  484.     {
  485.         collect(item, &buf[6]);
  486.         lcnt = 0;
  487.         Subsubtitle[0] = '\0';
  488.         item[strlen(item)] = '\n';
  489.  
  490. #ifdef BSD
  491.         if (sscanf(item, "%D , %D , %60s", &scnt, &lcnt, Subsubtitle))
  492. #else
  493.         if (sscanf(item, "%ld , %ld , %60[^\"),\n]", &scnt, &lcnt, Subsubtitle))
  494. #endif
  495.         {
  496.             Subsubtitle[TITLESIZE+1] = '\0';
  497.             if (lcnt + scnt + Lineno + 1 >= Pagesz)
  498.                 Lineno = Pagesz;            /* Force eject    */
  499.             else
  500.             {
  501.                 if (scnt < 0)
  502.                     scnt = 0;
  503.                 Lineno += scnt;
  504.                 Pointctr += TxtLineHgt * scnt;
  505.             }
  506.         }
  507.         return true;
  508.     }
  509.     else if (strncmp(buf, "_SUBTITLE", 9) == 0)    /* Else if SUBTITLE */
  510.     {
  511.         Subsubtitle[0] = '\0';
  512.         collect(Subtitle, &buf[9]);
  513.         Lineno = Pagesz;                        /* Force eject    */
  514.         return true;
  515.     }
  516.     else if (strncmp(buf, "_TITLE", 6) == 0)    /* Else if TITLE */
  517.     {
  518.         collect(Title, &buf[6]);
  519.         return true;
  520.     }
  521.     else if (strncmp(buf, "_EJECT", 6) == 0 ||
  522.          strncmp(buf, "_PAGE", 5) == 0)
  523.     {
  524.         Subsubtitle[0] = '\0';
  525.         Lineno = Pagesz;                        /* Force eject    */
  526.         return true;
  527.     }
  528.  
  529.     return false;            /* If no valid directive found    */
  530. }
  531.  
  532. _SPACE("4,20,printit")
  533. /*
  534.  *    printit - Print line.
  535.  *
  536.  *    Prints non-blank line from file adding line numbers and handles counted
  537.  *    blank lines.
  538.  *
  539.  *    Inputs:
  540.  *        fip        - (param) Pointer to file info structure.
  541.  *        Flineno    - Current line number in file.
  542.  *
  543.  *    Throughputs:
  544.  *        Lineno    - Incremented to indicate current line on page.
  545.  *        Blklns    - Cleared.
  546.  *
  547.  *    Calls:    expand_tabs, PrCtlCall, printline, sprintf
  548.  */
  549.  
  550. static void printit(fip)
  551. struct finfo    *fip;
  552. {
  553.     int    i;            /* Loop index        */
  554.     int    len;        /* Length of string    */
  555.     void    printline();
  556.     extern char    *expand_tabs();
  557.  
  558.     Lineno += Blklns;            /* Advance Lineno for skipped blank lines    */
  559.     for (i = 0; i < Blklns; ++i)    /* Print skipped blank lines, if any    */
  560.     {
  561.         Pointctr += TxtLineHgt;
  562.         if (NOpt)
  563.         {
  564.             MoveTo(border.left + 8, Pointctr);
  565.             len = sprintf(Tmpstr, "%5d", Flineno - Blklns + i);
  566.             drawstring(Tmpstr);
  567.         }
  568.     }
  569.  
  570.     Blklns = 0;
  571.  
  572.     Pointctr += TxtLineHgt;
  573.     MoveTo(border.left + 8, Pointctr);
  574.  
  575.     len = (NOpt) ? sprintf(Tmpstr, "%5d  ", Flineno) : 0;
  576.  
  577.     expand_tabs(Tmpstr + len, LineBuf, fip->ntabs) - Tmpstr;
  578.     drawstring(Tmpstr);
  579. }
  580.  
  581. _SPACE("4,10,upd_str_ptr")
  582. /*
  583.  *    upd_str_ptr - Update string pointer.
  584.  *
  585.  *    Returns the previous string pointer if str is the same string, otherwise
  586.  *    the new string is copied to a block in the heap and a pointer to the block
  587.  *    is returned.
  588.  *
  589.  *    Inputs:
  590.  *        oldp    - (param) Pointer to previous string.
  591.  *        str        - (param) Pointer to string.
  592.  *
  593.  *    Outputs:
  594.  *        Returns value of new pointer, 0L if appropriate or malloc failed.
  595.  *
  596.  *    Calls:    malloc, strcmp, strcpy, strlen
  597.  */
  598.  
  599.  static char    *upd_str_ptr(oldp, str)
  600.  char    *oldp;
  601.  char    *str;
  602.  {
  603.      char    *p;
  604.      extern char    *malloc();
  605.  
  606.     if (oldp && strcmp(oldp, str) == 0)
  607.         return oldp;
  608.     else
  609.     {
  610.         if (*str == '\000')
  611.             return 0L;
  612.         else
  613.         {
  614.             p = malloc(strlen(str)+1);
  615.             if (p == 0L)
  616.                 return 0L;
  617.             strcpy(p, str);
  618.             return p;
  619.         }
  620.     }
  621. }
  622.  
  623.  
  624. /*    End of laser.c    */